﻿//bibaoke.com

using System.Text.RegularExpressions;
using Less.Text;
using System.Collections.Generic;
using System;

namespace Less.SqlParser
{
    internal abstract class ReaderBase
    {
        private static Regex Pattern
        {
            get;
            set;
        }

        protected Word CurrentWord
        {
            get
            {
                return this.Context.CurrentWord;
            }
            private set
            {
                this.Context.CurrentWord = value;
            }
        }

        protected Word LastWord
        {
            get
            {
                return this.Context.LastWord;
            }
            private set
            {
                this.Context.LastWord = value;
            }
        }

        protected string Sql
        {
            get
            {
                return this.Context.Sql;
            }
        }

        protected int CurrentIndex
        {
            get
            {
                return this.Context.CurrentIndex;
            }
            private set
            {
                this.Context.CurrentIndex = value;
            }
        }

        protected Statement CurrentStatement
        {
            get
            {
                return this.Context.CurrentStatement;
            }
            set
            {
                this.Context.CurrentStatement = value;
            }
        }

        protected StatementCollection Statements
        {
            get
            {
                return this.Context.Statements;
            }
        }

        protected static HashSet<string> ActionNames
        {
            get;
            private set;
        }

        internal Context Context
        {
            get;
            set;
        }

        static ReaderBase()
        {
            ReaderBase.Pattern =
                @"(?<word>.*?)(?<separator>\s+|,|;|\(|\)|\[|$)".ToRegex(
                RegexOptions.Singleline |
                RegexOptions.Compiled);

            ReaderBase.ActionNames = new HashSet<string>(new string[]
            {
                "select", "insert", "update", "delete",
                "create", "alter", "modify",
            }, StringComparer.OrdinalIgnoreCase);
        }

        internal abstract ReaderBase Read();

        protected Word ReadWord()
        {
            Match match = ReaderBase.Pattern.Match(this.Sql, this.CurrentIndex);

            if (match.Success)
            {
                Group word = match.Groups["word"];
                Group separator = match.Groups["separator"];

                int wordEnd = word.Index + word.Length - 1;
                int separatorEnd = separator.Index + separator.Length - 1;

                this.CurrentIndex = separatorEnd + 1;

                this.LastWord = this.CurrentWord;

                this.CurrentWord = new Word
                {
                    Content = word.Value,
                    Separator = separator.Value,
                    Begin = word.Index,
                    WordEnd = wordEnd,
                    End = separatorEnd
                };

                return this.CurrentWord;
            }
            else
            {
                return null;
            }
        }

        protected Select CastToSelect()
        {
            if (this.CurrentStatement is Select)
            {
                return (Select)this.CurrentStatement;
            }
            else
            {
                return null;
            }
        }

        protected T Pass<T>() where T : ReaderBase, new()
        {
            T t = new T();

            t.Context = this.Context;

            return t;
        }
    }
}
